#include "hdu_handler.h"

const char* HduHandler::user_agent = "curl/7.22.0 (i686-pc-linux-gnu) 	\
									  libcurl/7.22.0 OpenSSL/1.0.1 		\
				  			  		  zlib/1.2.3.4 libidn/1.23 librtmp/2.3";

HduHandler::HduHandler(int curl_id, std::string cookie_dir, 
		int outpipe, int msgid, pthread_mutex_t *mutex_ptr):
		out_pipe(outpipe), msg_id(msgid), out_pipe_mutex_ptr(mutex_ptr),
		current_task("", "", "", "", "") {
	mycurl = new MyCurl(curl_id, get_cookie_path(cookie_dir.data(), "hdu", curl_id));
}

HduHandler::~HduHandler() {
	delete mycurl;
}

// curl的回调函数，保存header，body
size_t HduHandler::save_http_contents(char *ptr, size_t size, size_t nmemb, void *user_data) {
	((std::string*)user_data)->append(ptr, size * nmemb);
	//printf("%X size: %d\n", user_data, size*nmemb);
	return size * nmemb;
}

std::string HduHandler::find_language_id(const char *language) {
	for (int i = 0; i < Hdu::n_language; i++) {
		if (!strcmp(Hdu::hdu_language[i], language)) 
			return itoa_string(i);
	}
	return std::string("-1");
}

std::string HduHandler::login_data(const char *user_id, const char *passwd) {
	std::vector<PSS> data;
	data.push_back(std::make_pair("username", user_id));
	data.push_back(std::make_pair("userpass", passwd));
	data.push_back(std::make_pair("login", "Sign In"));
	return args_encode(data);
}

int HduHandler::login(const char *user_id, const char *passwd, void *user_data) {
	CURL* &curl = mycurl->curl;
	const char *cookie_path = mycurl->cookie_path.data();
	HttpResponse resp;

	std::string str_data = HduHandler::login_data(user_id, passwd);
	const char *data = str_data.data();
	
	printf("data: %s\n", data);

	curl_easy_reset(curl);
	//curl_easy_setopt(curl, CURLOPT_USERAGENT, HduHandler::user_agent);
	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
	curl_easy_setopt(curl, CURLOPT_URL, Hdu::url_login);
	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L);
	curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_path);
	curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_path);

	curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, HduHandler::save_http_contents);
	curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void*)(&resp.header));

	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HduHandler::save_http_contents);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)(&resp.body));

	CURLcode curl_res = curl_easy_perform(curl);
	if (curl_res != CURLE_OK)
		fprintf(stdin, "%s login error: %s\n", user_id, curl_easy_strerror(curl_res));
	
	//printf("%s\n", resp.header.data());
	//printf("%s\n", resp.body.data());

	return curl_res == CURLE_OK ? 0 : curl_res;
}

std::string HduHandler::submit_data(const char *problemid, const char *language, 
		const char *usercode) {
	std::vector<PSS> data;
	data.push_back(std::make_pair("check", "0"));
	data.push_back(std::make_pair("problemid", problemid));
	data.push_back(std::make_pair("language", find_language_id(language)));
	data.push_back(std::make_pair("usercode", usercode));
	return args_encode(data);
}

int HduHandler::submit(HduTask &task) {
	current_task = task;
	CURL *curl = mycurl->curl;
	const char *cookie_path  = mycurl->cookie_path.data();
	HttpResponse resp;

	std::string src = add_comment() + task.usercode;
	std::string str_data = HduHandler::submit_data(task.problemid.data(), task.language.data(), src.data());
	const char *data = str_data.data();

	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
	//curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent);
	curl_easy_setopt(curl, CURLOPT_URL, Hdu::url_submit);
	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L);
	curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_path);
	curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_path);
	curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, HduHandler::save_http_contents);
	curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void*)(&resp.header));

	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HduHandler::save_http_contents);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)(&resp.body));

	CURLcode curl_res = curl_easy_perform(curl);
	if (curl_res != CURLE_OK)
		fprintf(stdin, "submit error: %s\n", curl_easy_strerror(curl_res));
	
	//printf("%s\n", resp.header.data());
	//printf("%s\n", resp.body.data());

	return curl_res == CURLE_OK ? 0 : curl_res;
}


void HduHandler::get_judge_result() {
	char user_id[10];
	sprintf(user_id, "gvj%d", mycurl->id);
	std::string stream = parse_html(user_id);

	current_result = "";
	current_result += current_task.socket_fd  + "|";
	current_result += current_task.oj_name    + "|";
	current_result += stream;
	char str[20];
	sprintf(str, "%d|", current_result.length());
	current_result  = std::string(str) + current_result;
	printf("%s\n", current_result.data());
}

int HduHandler::send_result_to_listen() {
	int length = current_result.length();
	int remain = current_result.length();
	const char *str = current_result.data();

	pthread_mutex_lock(out_pipe_mutex_ptr);
	while (true) {
		ssize_t nbytes = write(out_pipe, str + length - remain, remain);
		if (nbytes > 0)  remain -= nbytes;
		if (remain <= 0) break;
	}
	pthread_mutex_unlock(out_pipe_mutex_ptr);
	printf("(%d) write out_pipe return\n", mycurl->id);
	return 0;
}
